using System;
using System.Collections.Generic;

public class EventMgr : Singleton<EventMgr>
{
    /// <summary>储存所有注册的消息事件的数据结构</summary>
    public Dictionary<int, LinkedList<Action<Message>>> allMessages = new Dictionary<int, LinkedList<Action<Message>>>();

    /// <summary>注册消息事件</summary>
    /// <param name="eventType">指定的消息类型</param>
    /// <param name="action">所注册的消息事件回调</param>\
    /// <param name="allowRepeat">是否允许注册相同的回调函数</param>
    public void RegisterEvent<T>(T eventType, Action<Message> action, bool allowRepeat = false) where T:IConvertible {
        int eventID = eventType.ToInt32(null);
        if (!allMessages.ContainsKey(eventID))
            allMessages.Add(eventID, new LinkedList<Action<Message>>());
        LinkedList<Action<Message>> messages = allMessages[eventID];//该EventType对应的所有事件
        if (messages.Contains(action) && allowRepeat == false)
            return;
        messages.AddLast(action);
    }

    /// <summary>移除某一消息类型下的某一个注册的事件</summary>
    /// <param name="eventType">该消息事件所属的消息类型</param>
    /// <param name="action">要移除的指定的消息事件</param>
    public void RemoveEvent<T>(T eventType, Action<Message> action) where T : IConvertible
    {
        int eventID = eventType.ToInt32(null);
        if (allMessages.ContainsKey(eventID) && allMessages[eventID].Contains(action))
            allMessages[eventID].Remove(action);
    }
    /// <summary>移除指定消息类型下的所有注册的事件</summary>
    /// <param name="eventType">要移除的消息类型</param>
    public void RemoveEvent<T>(T eventType)where T:IConvertible{
        int eventID = eventType.ToInt32(null);
        if (allMessages.ContainsKey(eventID))
            allMessages.Remove(eventID);
    }
    /// <summary>移除所有的注册的消息事件</summary>
    public void RemoveEvent() {
        allMessages?.Clear();
    }

    /// <summary>发送消息</summary>
    /// <param name="_eventType">指定的消息类型</param>
    /// <param name="_data">该消息所携带的参数</param>
    /// <param name="_sender">该消息发送者</param>
    public void SendEvent<T>(T _eventType, object _data = null, object _sender = null) where T : IConvertible
    {
        Message message = new Message
        {
            eventType = _eventType.ToInt32(null),
            data = _data,
            sender = _sender
        };
        SendEvent(message);
    }

    /// <summary>发送消息</summary>
    public void SendEvent(Message message)
    {
        allMessages.TryGetValue(message.eventType, out LinkedList<Action<Message>> messages);
        if (messages != null) {
            LinkedListNode<Action<Message>> node = messages.First;
            while (node != null)
            {
                LinkedListNode<Action<Message>> next = node.Next;
                node.Value?.Invoke(message);
                node = node.Next ?? next;
            }
        }
    }
}

public class Message
{
    public int eventType;
    public object sender;
    public object data;
}

public enum EventType
{
    ChracterClicked,
    SpeedChanged,
    ScaleChanged,
    AlphaChanged,
    SwitchMonotor,
    OnNtfStates,
}
